package edu.usc.csci538.hw6.screens;

import edu.usc.csci538.hw6.Utils;
import edu.usc.csci538.hw6.data.CalendarEntryManager;
import java.util.Calendar;
import java.util.Date;
import java.util.Vector;
import javax.microedition.lcdui.Canvas;
import javax.microedition.lcdui.Command;
import javax.microedition.lcdui.CommandListener;
import javax.microedition.lcdui.Display;
import javax.microedition.lcdui.Displayable;
import javax.microedition.lcdui.Graphics;
import javax.microedition.midlet.MIDlet;

/**
 *
 * @author yaoli
 */
public class MonthlyCalendar extends Canvas implements CommandListener {
    private Calendar currentDate;
    private MIDlet midlet;
    private Command viewCommand;
    
    public MonthlyCalendar(MIDlet midlet) {
        currentDate = Calendar.getInstance();
        currentDate.setTime(new Date(currentDate.getTime().getTime() - 8*60*60*1000L));    
        this.midlet = midlet;
        viewCommand = new Command("View", Command.SCREEN, 1);
        addCommand(viewCommand);
        setCommandListener(this);
    }
    public void setDate(Date date) {
        currentDate.setTime(date);
    }
    protected int daysInMonth() {
        switch (currentDate.get(Calendar.MONTH)) {
            case Calendar.JANUARY:
            case Calendar.MARCH:
            case Calendar.MAY:
            case Calendar.JULY:
            case Calendar.AUGUST:
            case Calendar.OCTOBER:
            case Calendar.DECEMBER:
                return 31;
            case Calendar.APRIL:
            case Calendar.JUNE:
            case Calendar.SEPTEMBER:
            case Calendar.NOVEMBER:
                return 30;
            default:
                if (currentDate.get(Calendar.YEAR) % 4 == 0) {
                    return 29;
                }
                return 28;
        }
    }
    protected int getDayOfWeek(int val) {
        switch (val) {
            case Calendar.MONDAY: return 1;
            case Calendar.TUESDAY: return 2;
            case Calendar.WEDNESDAY: return 3;
            case Calendar.THURSDAY: return 4;
            case Calendar.FRIDAY: return 5;
            case Calendar.SATURDAY: return 6;
            case Calendar.SUNDAY: return 0;
        }
        throw new RuntimeException();
    }
    // Returns the x location
    protected int getGridXForDate(int date) {
        Calendar cal = Calendar.getInstance();
        cal.setTime(currentDate.getTime());
        cal.set(Calendar.DATE, date);
        return getDayOfWeek(cal.get(Calendar.DAY_OF_WEEK));
    }
    protected int getGridYForDate(int date) {
        return (date + getGridXForDate(1)) / 7;
    }
    protected void paint(Graphics g) {
        setTitle(Utils.monthAsString(currentDate.get(Calendar.MONTH)) + " " + currentDate.get(Calendar.YEAR));
        
        g.setColor(0xFFFFFF);
        g.fillRect(0, 0, getWidth(), getHeight());
        g.setColor(0x000000);
        // computer cellheight and cellwidth
        int celloriginx = 20;
        int celloriginy = 45;
        int cellheight = (getHeight() - celloriginy * 2 /* Margin */) / 6;
        int cellwidth = (getWidth() - celloriginx * 2 /* Margin */) / 7;
        
        for (int k = 0; k <= 2; k++) {
            int daysofar = -getGridXForDate(1);
            for (int j = 0; j < 6; j++) {
                for (int i = 0; i < 7; i++) {
                    boolean activated = daysofar >= 0 && daysofar < daysInMonth();
                    boolean selected = currentDate.get(Calendar.DATE) == daysofar + 1;
                    int rectOriginX = celloriginx + cellwidth * i;
                    int rectOriginY = celloriginy + cellheight * j;
                    if (k == 0 && j == 0) {
                        g.setColor(0xCCCCCC);
                        g.drawRoundRect(
                          rectOriginX, rectOriginY - 20, cellwidth, 20, 10, 10);
                        g.drawString(Utils.numDayOfWeekAsString(i),
                                rectOriginX + 2, rectOriginY - 18, Graphics.TOP | Graphics.LEFT);
                    }
                    if (!activated) {
                        g.setColor(0xCCCCCC);
                    } else if (selected) {
                        g.setColor(0x0000FF);
                    } else {
                        g.setColor(0x000000);
                    }

                    if (k == 0 && !activated || k == 1 && activated || k == 2 && selected) {
                        g.drawRoundRect(
                          rectOriginX, rectOriginY, cellwidth, cellheight, 10, 10);
                    }
                    if (k == 2 && selected) {
                        g.drawRoundRect(
                            rectOriginX+1, rectOriginY+1, cellwidth-2, cellheight-2, 9, 9);
                        
                    }
                    if (k == 1 && activated || k == 2 && selected) {
                        g.drawString(Integer.toString(daysofar + 1),
                            rectOriginX + 5, rectOriginY + 3, Graphics.TOP | Graphics.LEFT);
                        Calendar cal = Calendar.getInstance();
                        cal.setTime(currentDate.getTime());
                        cal.set(Calendar.DATE, daysofar + 1);
                        Vector today = CalendarEntryManager.get().getEntriesForDate(cal);
                        if (today.size() > 0) {
                            g.drawString("x",
                                rectOriginX + cellwidth - 10, rectOriginY + cellheight, Graphics.BOTTOM | Graphics.LEFT);
                        }
                    }
                    daysofar++;
                }
            }
        }
    }
    protected void keyPressed(int keyCode) {
        long offset = 0;
        long day = 24*60*60*1000L;
        switch (keyCode) {
            case -3:
            case Canvas.LEFT:
                offset = -day; break;
            case -4:
            case Canvas.RIGHT:
                offset = day; break;
            case -2:
            case Canvas.DOWN:
                offset = 7 * day; break;
            case -1:
            case Canvas.UP:
                offset = -7 * day; break;
            case -5:
            case Canvas.FIRE:
                showDayViewList();
                break;
            default:
                return;
        }
        
        currentDate.setTime(new Date(currentDate.getTime().getTime() + offset));
        repaint();
        serviceRepaints();
    }

    protected void showDayViewList() {
        DayViewList list = new DayViewList();
        list.setDate(currentDate.getTime());
        list.onRender();
        list.setMidlet(midlet);
        Display.getDisplay(midlet).setCurrent(list);
    }
    
    public void commandAction(Command cmd, Displayable displayable) {
        if (cmd == viewCommand) {
            showDayViewList();
        }
    }
}
